﻿using Common.Logging;
using Common.Logging.Configuration;
using Common.Logging.Log4Net;
using Dubbo.Common.Container;
using Dubbo.Common.Utils;
using log4net.Appender;
using log4net.Config;
using log4net.Core;
using log4net.Layout;
using log4net.Repository.Hierarchy;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dubbo.Container.Log4Net
{
    [Export(typeof(IContainer))]
    [ExportMetadata("Name", "log4net")]
    public class Log4NetContainer : IContainer
    {
        public const string LOG4NET_FILE = "dubbo.log4net.file";

        public const string LOG4NET_LEVEL = "dubbo.log4net.level";

        public const string LOG4NET_SUBDIRECTORY = "dubbo.log4net.subdirectory";

        public const string DEFAULT_LOG4NET_LEVEL = "ERROR";

        public void Start()
        {
            string file = ConfigUtils.Get(LOG4NET_FILE);
            if (!string.IsNullOrEmpty(file))
            {
                NameValueCollection properties = new NameValueCollection();
                properties["configType"] = "EXTERNAL";
                LogManager.Adapter = new Log4NetLoggerFactoryAdapter(properties);
                //XmlConfigurator.Configure();

                Hierarchy hierarchy = (Hierarchy)log4net.LogManager.GetRepository();

                PatternLayout patternLayout = new PatternLayout();
                patternLayout.ConversionPattern = "%d [%t] %-5p - %m%n";
                patternLayout.ActivateOptions();

                RollingFileAppender roller = new RollingFileAppender();
                roller.Layout = patternLayout;
                roller.File = file;
                roller.AppendToFile = true;
                roller.RollingStyle = RollingFileAppender.RollingMode.Composite;
                roller.MaxSizeRollBackups = 50;
                roller.MaximumFileSize = "10MB";
                roller.StaticLogFileName = false;
                roller.DatePattern = "yyyy-MM-ddTHH.lo\\g";
                roller.ActivateOptions();
                hierarchy.Root.AddAppender(roller);

                hierarchy.Root.Level = Level.Info;
                hierarchy.Configured = true;
            }

            string subdirectory = ConfigUtils.Get(LOG4NET_SUBDIRECTORY);
            if (!string.IsNullOrEmpty(subdirectory))
            {
                var loggers = log4net.LogManager.GetCurrentLoggers();
                foreach (LogImpl log in loggers)
                {
                    if (log != null)
                    {
                        var appenders = ((Logger)log.Logger).Appenders;
                        foreach (var appender in appenders)
                        {
                            if (appender is FileAppender)
                            {
                                FileAppender fa = (FileAppender)appender;
                                string f = fa.File;
                                if (!string.IsNullOrEmpty(f))
                                {
                                    int i = f.Replace('\\', '/').LastIndexOf('/');
                                    string path;
                                    if (i == -1)
                                    {
                                        path = subdirectory;
                                    }
                                    else
                                    {
                                        path = f.Substring(0, i);
                                        if (!path.EndsWith(subdirectory))
                                        {
                                            path = path + "/" + subdirectory;
                                        }
                                        f = f.Substring(i + 1);
                                    }
                                    fa.File = path + "/" + f;
                                    fa.ActivateOptions();
                                }
                            }
                        }
                    }
                }
            }
        }

        public void Stop()
        {
        }
    }
}
